<template>
    <div id="tw_table">
        <!-- 表格头部 操作按钮 -->
        <slot name="tableHeader"></slot>
        <div class="table-header pb15 tw_clr" v-if="isTableHeader">
            <div class="table-l">
                <span v-show="multipleSelection.length > 0 && !isRradio" class="num tw_cl"
                    style="color: var(--el-text-color-primary);">
                    <el-icon class="mr5 ml15" :size="14" color="var(--el-color-primary)">
                        <WarningFilled />
                    </el-icon>
                    已选择
                    <span class="check-num" style="color: var(--el-color-primary)"> {{ multipleSelection.length }}
                    </span>
                    条记录
                </span>
                <slot name="table-l"></slot>
            </div>
            <div class="table-c">
                <slot name="table-c"></slot>
            </div>
            <div class="table-r tw_cl">
                <slot name="table-r"></slot>

                <div class="tw_cl" v-if="showHeadBtns">
                    <div class="head_btn"
                         v-show="item && (item.formatter ? item.formatter(item, i) : true)"
                         v-for="(item, i) in headBtns" :key="i">
                        {{}}
                        <el-button type="primary" v-if="item" :disabled="item.disabled"
                                   @click="item?.click(item)" :size="size==='small'?'small':''">
                            <svg-icon size="14px" v-if="item.icon" :color="i ? '' : '#fff'" style="margin-right:8px;"
                                      :icon-class="item?.icon"></svg-icon>
                            {{ item?.name }}
                        </el-button>
                    </div>
                </div>
            </div>
        </div>
        <slot name="tableBotHeader"></slot>
    
        <el-table ref="table" :id="id" :data="dataList" :height="tableHeight || getH" :highlight-current-row="highlightCurrentRow" :size="size" :stripe="stripe" :border="border"
            v-loading="loading" element-loading-text="加载中..." :element-loading-background="loadingBg" @row-click="rowCheck" @select="checkSelect" :row-class-name="rowClassName"
            @selection-change="selectionChange" @current-change="tableCurrentChange" center class="w" :empty-text="emptyText">
            <!-- 多选 -->
            <el-table-column :selectable="selectable" current-row-key="selection" align="center" :fixed="checkFixed" header-align="center"
                type="selection" v-if="isCheck" width="50" />
            <!-- 序号 -->
            <el-table-column :index="indexMethod" align="center" :fixed="indexFixed" header-align="center" label="序号"
                type="index" v-if="showIndex" width="65" />

            <template v-for="(item, index) in columns" :key="TwTable">
                <template v-if="!item.hidden">
                    <template v-if="item.formatter">
                        <el-table-column resizable :show-overflow-tooltip="item.showOverflowTooltip!==false" :type="item.type" :label="item.label" :sortable="item.sortable" :width="item.width" :fixed="item.fixed" :class-name="item.className" :formatter="item.formatter">
                            <!-- 自定义 header (使用组件渲染 tsx 语法) -->
                            <template #header v-if="item.renderHeader">
                                <component :is="item.renderHeader" :row="item"></component>
                            </template>
                        </el-table-column>
                    </template>
                    <el-table-column v-else resizable show-overflow-tooltip :prop="item.prop" :type="item.type" :class-name="item.className"
                                     :label="item.label" :sortable="item.sortable" :width="item.width" :fixed="item.fixed">
                        <!-- 自定义 header (使用组件渲染 tsx 语法) -->
                        <template #header v-if="item.renderHeader">
                            <component :is="item.renderHeader" :row="item"></component>
                        </template>
        
                        <!-- 自定义配置每一列 slot（使用作用域插槽） -->
                        <template #default="scope">
                            <!--                        <slot :name="item.prop" :row="scope.row">-->
<!--                            <template v-if="notNull(scope.row?.[item.prop]) || scope.row?.[item.prop] == 0">-->
                            <template v-if="notNull(scope.row?.[item.prop]) && scope.row?.[item.prop] != 0">
                                <template v-if="!!item.color">
                                    <span :style="`color: ${item.color}`">
                                        {{!!item.filter ? oEnumerate?.[item.filter]?.[scope.row[item.prop]]
                                        : scope.row?.[item.prop] }}
                                    </span>
                                </template>
                                <template v-else>
                                    {{!!item.filter ? oEnumerate?.[item.filter]?.[scope.row[item.prop]] :
                                    scope.row?.[item.prop] }}
                                </template>
                            </template>
                            <template v-else>-</template>
                            <!--                        </slot>-->
                        </template>
                    </el-table-column>
                </template>
                
            </template>
            <template v-if="tableBtns.prop">
                <el-table-column resizable :prop="tableBtns.prop" :type="tableBtns.type"
                    :label="tableBtns.label" :width="tableBtns.width" :fixed="tableBtns.fixed" :header-align="tableBtns.align || 'left'">
                    <!-- 自定义 header (使用组件渲染 tsx 语法) -->
                    <template #header v-if="tableBtns.renderHeader">
                        <component :is="tableBtns.renderHeader" :row="tableBtns"></component>
                    </template>

                    <!-- 自定义配置每一列 slot（使用作用域插槽） -->
                    <template #default="{ row, column, $index }">
                        <p class="tw_cl" style="flex-wrap: nowrap;">
                            <template v-for="(item, i) in tableBtns.btns">
                                <template v-if="item.formatter">
                                    <template v-if="item.formatter(row, column, $index)">
                                        <el-tooltip :key="i" effect="dark" placement="top-start">
                                            <template #content> {{ item.name }}</template>
                                            <el-icon @click.stop="item.click(row, column, $index)" size="20px" class="pointer mr10">
                                                <svg-icon :icon-class="item.icon" :color="['shanchu','jinyong'].includes(item.icon)?'#FF616E':item.color"></svg-icon>
                                            </el-icon>
                                        </el-tooltip>
                                    </template>
                                </template>
                                <template v-else>
                                    <el-tooltip :key="i" effect="dark" placement="top-start">
                                        <template #content> {{ item.name }}</template>
                                        <el-icon @click.stop="item.click(row, column, $index)" size="20px" class="pointer mr10">
                                            <svg-icon :icon-class="item.icon" :color="['shanchu','jinyong'].includes(item.icon)?'#FF616E':item.color"></svg-icon>
                                        </el-icon>
                                    </el-tooltip>
                                </template>
                            </template>
                        </p>
                    </template>
                </el-table-column>
            </template>
        </el-table>
        <!--  分页  -->
        <tw-pagination v-if="showPagination" v-model:currentPage="tableParams.pageNumber" :size="size"
            v-model:pageSize="tableParams.pageSize" :total="total" :small="small" :pageSizesArr="pageSizesArr" :background="background" :layout="layout"
            @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange"></tw-pagination>
    </div>

</template>

<script setup lang="tsx" name="TwTable">
import { commonApi } from "../../api/common";
import { onActivated } from "vue";
import {debounce} from "@/utils";
import  { WarningFilled } from '@element-plus/icons-vue'
defineOptions({
    name: 'TwTable'
})
let obj = getCurrentInstance()
console.log(obj);

// @ts-ignore
const { proxy } = getCurrentInstance()
// @ts-ignore
const { url, id, method, columns, lists, tableParams, tableHeight, showPagination, botHeight, indexFixed, isCheck, checkFixed, showIndex, size, stripe, border, pageSizesArr, tableBtns, small, headBtns, tableCallback, rowClassName, isTableHeader, isLoadStatus, autoScrollToTop, selectable, isRradio, background, layout, loadingBg, emptyText } = defineProps({
    url: { type: String, default: '' },                                  // 表格请求地址
    id: { type: String, default: '' },                                  // 表格id属性，动态计算id
    method: { type: String, default: 'post' },                           // 表格请求类型
    columns: { type: Array, default: () => [] },                          // 表格列渲染数据
    lists: { type: Array, default: () => [] },                        // 表格渲染数据
    tableParams: { type: Object, default: () => { return { pageNumber: 1, pageSize: 25 } } },                     // 表格请求数据
    tableHeight: { type: Number, default: 0 },                     // 表格固定高度
    isRradio: { type: Boolean, default: false },                    // 单选
    showPagination: { type: Boolean, default: true },                    // 分页显示开关
    botHeight: { type: Number, default: 50 },                            // 是分页栏加上边距加底部空白位置高度
    indexFixed: { type: Boolean, default: false },                       // 索引左侧定位开关
    isCheck: { type: Boolean, default: false },                          // checkbox显示开关
    checkFixed: { type: String, default: 'left' },                       // checkbox左侧定位开关
    showIndex: { type: Boolean, default: false },                        // 索引显示开关
    size: { type: String, default: 'large' },                            // table 大小配置
    stripe: { type: Boolean, default: true },                            // 斑马纹显示开关
    border: { type: Boolean, default: false },                           // 边框线显示开关
    pageSizesArr: { type: Array, default: () => [25, 50, 100] },          // 分页页码
    tableBtns: { type: Object, default: (row) => row || {} },             // 单例按钮渲染数据
    small: { type: Boolean, default: false, },                            // 每页显示条数
    headBtns: { type: Array, default: () => [] },                         // 顶部操作按钮
    isTableHeader: { type: Boolean, default: true, },                    // 默认显示表格顶部操作栏
    isLoadStatus: { type: Boolean, default: false, },                    // 默认首次不加载table数据
    highlightCurrentRow: { type: Boolean, default: true, },                 // 是否高亮显示当前选中行
    rowClassName: { type: Function, default: () => {}, },                   // 行样式名称
    selectable: { type: Function, default: () => true, },                     // isCheck必须为true  用于判断选项是否可以点击
    autoScrollToTop: { type: Boolean, default: true, },             // 请求数据后是否自动滚动到顶部
    layout:{ type: String, default: 'total, prev, pager, next, sizes, jumper' },  // 分页布局默认配置
    background:{ type: Boolean, default: true },                                // 表格的背景颜色
    loadingBg:{ type: String, default: 'rabg(225,225,225)' },                   // 表格接口加载状态下背景颜色
    emptyText:{ type: String, default: '暂无数据' }                             //列表无数据时展示的文字
})
let radioCss = $ref('') //如果是单选 则隐藏 表头上的checkbox
radioCss = isRradio?'none':'initial'
const oEnumerate  = {};
// @ts-ignore
let table = $ref(null)
// @ts-ignore
let getH = $ref(600)
let dataList = $ref([])
let loading = $ref(false)
let total = $ref(0)
let multipleSelection = $ref([])
let showHeadBtns = $ref(true)


onActivated(() => {
    showHeadBtns = false
    nextTick(() => {
        showHeadBtns = true
    })
})

let eimts = defineEmits(['currentChange', 'sizeChange', 'checkSelect', 'selectionChange', 'checkSelect', 'rowCheck', 'tableCallback', 'tableCurrentChange'])

// 请求表格数据 TODO 这里需要做一个参数校验并给出提示[]
const getTable = () => {
    if (!loading)
        loading = true
    commonApi(url, tableParams, method).then(res => {
        if(res === null) {
            dataList = []
            total = 0
            loading = false
            return
        }
        loading = false
        total = res.total
        dataList = res.rows
        eimts('tableCallback', dataList, res)
        if(!tableHeight) {
            setTableDataHeight()
        }
        if(autoScrollToTop){
            scrollTop()
        }
    }).catch(() => {
        loading = false
        if(!tableHeight) {
            setTableDataHeight()
        }
    })
}

const notNull = (flag) => {
    return flag !== null && flag !== '' && flag !== 'null' && flag !== undefined
}


const scrollTop = () => {
    nextTick(() => {
        let dom = document.getElementsByClassName('el-table')[0]
        if (id) {
            dom = document.getElementById(id)
        }
        table.setScrollTop(0)
        // dom.querySelector('.el-table__body').scrollTop = 0
    })
}

if (notNull(url)) {
    // if(JSON.stringify(store.getters.oEnumerate) === "{}"){
    //     loading = true
    //     getTable()
    // }else {
    //     loading = true
    //     getTable()
    // }
    if(!isLoadStatus){
        loading = true
        getTable()
    }
} else {
    // 如果是默认传递tabel数据，必须经过数据监听并更新数据
    watch(() => lists, (newValue, oldValue) => {
        dataList = newValue
        setTimeout(()=>{
            if(!tableHeight) {
                setTableDataHeight()
            }
        },500)
    }, { immediate: true })
    // watch(() => total, (newValue, oldValue) => {
    //     debugger
    //     total = newValue
    // }, { immediate: true })
}



const filterHeadBtns = computed(() => {
    let arr = []
    for (let i = 0; i < headBtns.length; i++) {
        if(headBtns[i] && (headBtns[i].formatter ? headBtns[i].formatter(headBtns[i], i) : true)){
            arr.push(headBtns[i])
        }
    }
    return arr
})

// 总条数
const handleSizeChange = (val) => {
    tableParams.pageSize = val
    tableParams.pageNumber = 1
    if (notNull(url)) {
        getTable()
    }
    eimts('handleSizeChange', val)
}

// 当前跳转页
const handleCurrentChange = (val) => {
    tableParams.pageNumber = val
    if (notNull(url)) {
        getTable()
    }
    eimts('handleCurrentChange', val)
}

const tableCurrentChange = (row) => {
    eimts('tableCurrentChange', row)
}

// @ts-ignore
const setTableDataHeight = debounce(() => {
    let layout = document.getElementById('app')
    if (layout && table) {
        nextTick(() => {
            let dom = document.getElementsByClassName('el-table')[0]
            if (id) {
                dom = document.getElementById(id)
            }
            if (!dom) {
                setTimeout(() => {
                    setTableDataHeight()
                }, 1000)
                return
            }
            let allXy = getOffsetLeft(dom)
            if(allXy.top == 0) return;  // 等于0等同于找不元素，直接终止
            let layoutH = layout.clientHeight || window.innerHeight
            // if (!showPagination || tableParams.pageSize > total) (layoutH = layoutH + 52)  // 52 是分页栏加上边距高度
            if (!showPagination) (layoutH = layoutH + 52)  // 52 是分页栏加上边距高度
            let height = layoutH - allXy.top - botHeight      // 107 是分页栏加上边距加底部空白位置高度
            if (height < 120) {
                getH = 120
            } else {
                getH = height
            }
        })
    }
})

// 表格的check选择
const selectionChange = (row) => {
    let status = row.length > multipleSelection.length ? true : false
    // if (row.length === dataList.length || (multipleSelection.length != dataList.length && row.length === 0)) {
    //     eimts('checkSelect', { arr: row, row, status })
    // }
    if(!isRradio){
        multipleSelection = row
    }
    eimts('selectionChange', row, status)
}
// 当用户手动勾选数据行的 Checkbox 时触发的事件
const checkSelect = (arr, row) => { // item为空数组就是反选
    if (isCheck) {
        let status = arr.length > multipleSelection.length ? true : false
        if (isRradio) {
            if(multipleSelection.length == 0){
                multipleSelection = [row]
                table.toggleRowSelection(row, true)
            }else {
                if(multipleSelection[0] != row){
                    clearSelection()
                    multipleSelection = [row]
                    table.toggleRowSelection(row, true)
                }else {
                    multipleSelection = []
                    clearSelection()
                }
            }
        }else {
            multipleSelection = arr
        }
        eimts('checkSelect', { arr, row, status })
    } else {
        ElMessage.warning('请把选择框开关打开')
    }
}
// 设置表格行数据选择
const toggleRowSelection = (rows, status) => {
    if (isCheck) {
        nextTick(()=>{
            let lists = dataList
            rows.forEach(row => {
                for (let i = 0; i < dataList.length; i++) {
                    if (lists[i][status] == row[status]) {
                        let item = lists[i]
                        table.toggleRowSelection(item)
                        multipleSelection.push(item)
                    }
                }
            });
        })
        
    } else {
        ElMessage.warning('请打开checkbox相关配置')
    }
}
// 获取table全部list的checkbox
const getAllCheck = () => {
    return table.getSelectionRows()
}
// 设置table全部list的checkbox为true
const setAllCheck = () => {
    table.toggleAllSelection()
}
// 清空用户的选择
const clearSelection = () => {
    table.clearSelection()
}
// 点击当前行
const rowCheck = (item) => {
    if(isRradio){
        if(multipleSelection.length == 0){
            multipleSelection = [item]
            table.toggleRowSelection(item)
        }else {
            clearSelection()
            if(multipleSelection[0] != item){
                multipleSelection = [item]
                table.toggleRowSelection(item)
            }else {
                multipleSelection = []
            }
        }
    }
    eimts('rowCheck', item)
}

const setTableLists = (lists) => {
    dataList = lists
}

const setTableTotal = (num) => {
    total = num
}

const setCurrentRow = (data) => {
    table.setCurrentRow(data)
}
// 递归计算上，左边距值
const getOffsetLeft = (obj) => {
    let tmp = obj.offsetTop
    let lmp = obj.offsetLeft
    let node = obj.offsetParent
    while (node != null) {
        tmp += node.offsetTop
        lmp += node.offsetLeft
        node = node.offsetParent
    }
    return { top: tmp, left: lmp }
}
// 获取当前序列号
const indexMethod = (index) => {
    if (showPagination) {
        return (tableParams.pageNumber - 1) * tableParams.pageSize + TwTable + 1
    } else {
        return TwTable + 1;
    }
}

// 抛出获取列表数据
const getTableList = () =>{
    return dataList
}

// @ts-ignore
onMounted(() => {
    if(!tableHeight){
        // setTableDataHeight()
        window.addEventListener('resize', setTableDataHeight)
    }
    
})

// @ts-ignore
onUnmounted(() => {
    if(!tableHeight)
    window.removeEventListener('resize', setTableDataHeight, true)
})

defineExpose({ dataList, setTableDataHeight, selectionChange, checkSelect, toggleRowSelection, getTable, getAllCheck, setAllCheck, clearSelection, rowCheck, setTableLists, setTableTotal, setCurrentRow, getTableList })

</script>



<style scoped lang="scss">
#tw_table {
    padding: 20px 20px 0;
    &:focus {outline: none}
    :deep(.el-table) {border-radius: 12px;}
    :deep(.el-table td.el-table__cell, .el-table th.el-table__cell.is-leaf) {border-bottom: none}
    :deep(.el-table .el-table__header-wrapper .el-table-column--selection .el-checkbox ) {display: v-bind(radioCss)}
    
    /*:deep(.el-table-fixed-column--right):nth-child(3n+1) { background: rgba(0,0,0,0)}*/
    :deep(.el-table th.el-table__cell) {background: var(--tw-table-header)}
    :deep(.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell) {background: var(--tw-table-cell)}
    :deep(.el-table--striped .el-table__body .current-row td.el-table__cell) {background: #ffe6b0 !important;color: #606266;}
    :deep(tr.hover-row>td.el-table__cell) {background: #ffe6b0 !important;color: #606266;}
    .head_btn {margin-left: 15px;}
    :deep(.el-popper) {max-width: 640px;}
}
</style>
